package com.moorror.codegenvel.view.window.codegenxrender.tree;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.moorror.codegenvel.common.dialog.MRDialogInputName;
import com.moorror.codegenvel.common.notification.CodeGenByVelocityNotifier;
import com.moorror.codegenvel.common.tree.MTTreeCell;
import com.moorror.codegenvel.common.tree.TreePanelMark;
import com.moorror.codegenvel.common.tree.TreeRightPanelJson;
import com.moorror.codegenvel.common.tree.actions.*;
import com.moorror.codegenvel.common.tree.enums.AddSubTreeNodeType;
import com.moorror.codegenvel.common.utils.JsonUtils;
import com.moorror.codegenvel.constant.CodeGenByVelocityConstant;
import com.moorror.codegenvel.db.mysql.utils.HikaricpUtils;
import com.moorror.codegenvel.db.sqlite.dao.BaseDAO;
import com.moorror.codegenvel.db.sqlite.dao.impl.CodeGenSceneTemplateDaoImpl;
import com.moorror.codegenvel.db.sqlite.dao.impl.CodeGenTemplateDaoImpl;
import com.moorror.codegenvel.db.sqlite.dao.impl.CodeGenXRenderTableConfigDaoImpl;
import com.moorror.codegenvel.db.sqlite.entity.*;
import com.moorror.codegenvel.utils.GuiUtils;
import com.moorror.codegenvel.utils.JacksonUtils;
import com.moorror.codegenvel.view.component.CodeGenByVelocityComponent;
import com.moorror.codegenvel.view.component.TabContentRightShow;
import com.moorror.codegenvel.view.window.codegen.CodeGenLeft;
import com.moorror.codegenvel.view.window.codegen.domain.ExtractFileDesc;
import com.moorror.codegenvel.view.window.codegen.tree.MTTreeCellCodeGenData;
import com.moorror.codegenvel.view.window.codegenxrender.utils.TabLeftXRenderUtils;
import com.moorror.codegenvel.view.window.codegenxrender.view.NameTableConfigPanel;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.util.*;

/**
 * @Author jiyanghuang
 * @Date 2024/4/11 23:14
 */
public class MTTreeCellCodeGenXRenderNameTableConfig implements MTTreeCell {

    private Project project;

    private List<MTTreeCellCodeGenData> mockDatas = Lists.newArrayList();
    @Getter
    private TreeRightPanelJson treeRightPanelJson;

    @Getter
    private NameTableConfigPanel panel;

    /**
     * 真实的数据对象
     */
    @Getter
    private CodeGenXRenderTableConfig model;

    public MTTreeCellCodeGenXRenderNameTableConfig(Project project, CodeGenXRenderTableConfig model) {
        this.project = project;
        this.model = model;
    }


    @Override
    public String cellShow() {
        return model.getNameTableScene();
    }

    @Override
    public Icon iconSelected() {
        return GuiUtils.SCENE;
    }

    @Override
    public Icon iconUnselected() {
        return GuiUtils.SCENE;
    }

    @Override
    public AddSubTreeNodeType addSubTreeNodeType() {
        return AddSubTreeNodeType.DIALOG;
    }

    @Override
    public DefaultMutableTreeNode buildSubTreeNode(String jsonStr, TreePanelMark treePaneLMark) {
        CodeGenTemplate codeGenTemplate = CodeGenTemplate.of(jsonStr);
        model.addChildren(codeGenTemplate);
        MTTreeCellCodeGenData mockScene = new MTTreeCellCodeGenData(project, codeGenTemplate);
        DefaultMutableTreeNode sequenceTreeNode = new DefaultMutableTreeNode(mockScene);
        return sequenceTreeNode;
    }

    @Override
    public void addSubTreeNodeDialog(JTree tree, DefaultMutableTreeNode mutabLeTreeNode, TreePanelMark treePaneLMark) {
        CodeGenLeft mockLeft = (CodeGenLeft) treePaneLMark;
        new MRDialogInputName("", "template name", mockLeft.fetchProject(), (form) -> {
            CodeGenTemplate codeGenTemplate = AbEntity.of(CodeGenTemplate.class);
            codeGenTemplate.setName(form.getInputName().getText());
            return BaseDAO.checkExistAdd(codeGenTemplate, CodeGenTemplateDaoImpl.getInstance(), CodeGenTemplate::getName, () -> {
                DefaultMutableTreeNode chiLdNode = buildSubTreeNode(form.getInputName().getText(), treePaneLMark);
                addSubTreeNode(tree, mutabLeTreeNode, treePaneLMark, chiLdNode);
                /**
                 * 添加关联关系
                 */
                CodeGenSceneTemplate codeGenSceneTemplate = AbEntity.of(CodeGenSceneTemplate.class);
                codeGenSceneTemplate.setScene(model.getNameTableScene());
                codeGenSceneTemplate.setTemplate(codeGenTemplate.getName());
                CodeGenSceneTemplate ua = BaseDAO.connWrap((conn) -> {
                    return CodeGenSceneTemplateDaoImpl.getInstance().insert(conn, codeGenSceneTemplate);
                });
                if(null == ua){
                    return Pair.of(false, " add sceneTemplate fail ");
                }
                return Pair.of(true, null);
            });
        }).ofDialogShow();
    }

    @Override
    public void treeSelectionListener(JTree tree, DefaultMutableTreeNode mutableTreeNode, TreePanelMark treePanelMark) {
        try {
            if (null == panel) {
                panel = new NameTableConfigPanel(project, model);
            }
            TabContentRightShow tabContentRightShow = CodeGenByVelocityComponent.getInstance(project).findInstance(TabContentRightShow.class);
            tabContentRightShow.updatePanel(panel);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public ActionGroup rightClickActionGroup(JTree tree, DefaultMutableTreeNode mutableTreeNode, DefaultActionGroup defaultActionGroup, TreePanelMark treePanelMark) {
        defaultActionGroup.add(new SaveRightContentSqliteAllAction(treePanelMark, "saveToSqlite", "save to sqlite"));
        if(CodeGenByVelocityConstant.PLUGIN_FOR_SELF){
            defaultActionGroup.add(new TransferCallbackTreeSelectAction(treePanelMark, "Fetch Saved Schema", "Fetch Saved Schema", AllIcons.Actions.Find, this::fetchSaveSchema));
            defaultActionGroup.add(new TransferCallbackTreeSelectAction(treePanelMark, "Update Saved Schema", "Update Saved Schema", AllIcons.Actions.MenuSaveall, this::updateSaveSchema));
        }
        return defaultActionGroup;
    }

    @Override
    public void genCodeVelocity(TreePanelMark treePanelMark, DefaultMutableTreeNode mutableTreeNode) {
        if (mutableTreeNode.getChildCount() >= 0) {
            List<DefaultMutableTreeNode> genList = Lists.newArrayList();
            for (Enumeration<?> e = mutableTreeNode.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode) e.nextElement();
                if(n instanceof DefaultMutableTreeNode){
                    DefaultMutableTreeNode sub = (DefaultMutableTreeNode)n;
                    genList.add(sub);
                }
            }
            if(CollectionUtils.isNotEmpty(genList)){
                Collections.sort(genList, new Comparator<DefaultMutableTreeNode>() {
                    @Override
                    public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) {
                        String one = orderGen(o1);
                        String two = orderGen(o2);
                        return Integer.valueOf(one) - Integer.valueOf(two);
                    }
                });
                for(DefaultMutableTreeNode treeNode : genList){
                    MTTreeCellCodeGenData mtTreeCellCodeGenData = (MTTreeCellCodeGenData)treeNode.getUserObject();
                    mtTreeCellCodeGenData.genCodeVelocity(treePanelMark, treeNode);
                }
            }
        }
    }

    @Override
    public List<MTTreeCell> subTreeCell() {
        return (List) mockDatas;
    }

    @Override
    public void saveRightContentSqlite(TreePanelMark treePanelMark) {
        try {
            /**
             * 界面没有打开，没有填充数据
             */
            if(null == panel){
                return;
            }
            /**
             * 右边得有统一的 fetchValue 然后保存
             */
            panel.fetchValue();

            /**
             * 更新表
             */
            BaseDAO.update(CodeGenXRenderTableConfigDaoImpl.getInstance(), model);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    @Override
    public void deleteRightContentFromSqlite(DefaultMutableTreeNode mutableTreeNode, TreePanelMark treePanelMark) {
//        try {
//            BaseDAO.manyToManyDelete(CodeGenSceneDaoImpl.getInstance(), CodeGenSceneTemplateDaoImpl.getInstance(), CodeGenTemplateDaoImpl.getInstance(), codeGenScene, (st, t) -> {
//                CodeGenTemplate codeGenTemplate = (CodeGenTemplate) t;
//                CodeGenSceneTemplate codeGenSceneTemplate = AbEntity.of(CodeGenSceneTemplate.class);
//                codeGenSceneTemplate.setScene(st.getName());
//                codeGenSceneTemplate.setTemplate(codeGenTemplate.getName());
//                return codeGenSceneTemplate;
//            });
//            this.removeCurrent(treePanelMark.jTree(), mutableTreeNode);
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
    }

    @Override
    public void copyGenNewTree(TreePanelMark treePanelMark, DefaultMutableTreeNode mutableTreeNode) {
//        CodeGenLeft mockLeft = (CodeGenLeft) treePanelMark;
//        new MRDialogInputName("", "New Scene Name", treePanelMark.fetchProject(), (form) -> {
//            CodeGenScene codeGenSceneNew = AbEntity.of(CodeGenScene.class);
//            codeGenSceneNew.setName(form.getInputName().getText());
//            return BaseDAO.checkExistAdd(codeGenSceneNew, CodeGenSceneDaoImpl.getInstance(), CodeGenScene::getName, () -> {
//                if(CollectionUtils.isNotEmpty(codeGenScene.getChildren())){
//                    BaseDAO.copyMMN(codeGenSceneNew.getName(),CodeGenSceneTemplateDaoImpl.getInstance(), codeGenScene.getChildren(), CodeGenSceneTemplate.class, null);
//                }
//                /**
//                 * 更新树
//                 */
//                treePanelMark.treeReload(treePanelMark.rootTreeNode(), () -> {
//                    List<CodeGenScene> codeGenScenes = CodeGenSceneDaoImpl.getInstance().searchLikeMTM(codeGenSceneNew.getName());
//                    TreeCellEntityUtils.genTreeRootAppend(treePanelMark.rootTreeNode(), project, codeGenScenes);
//                });
//                return Pair.of(true, null);
//            });
//        }).ofDialogShow();
    }

    public Pair<Boolean, String> addTemplate(JTree tree, DefaultMutableTreeNode mutabLeTreeNode, TreePanelMark treePaneLMark,ExtractFileDesc extractFileDesc){
//        CodeGenTemplate codeGenTemplate = AbEntity.of(CodeGenTemplate.class);
//        codeGenTemplate.setName(extractFileDesc.getFileName());
//        codeGenTemplate.setContent(extractFileDesc.getFileContent());
//        return BaseDAO.checkExistAdd(codeGenTemplate, CodeGenTemplateDaoImpl.getInstance(), CodeGenTemplate::getName, () -> {
//            DefaultMutableTreeNode chiLdNode = buildSubTreeNode(extractFileDesc.getFileName(), treePaneLMark);
//            MTTreeCellCodeGenData cellCodeGenData = (MTTreeCellCodeGenData)chiLdNode.getUserObject();
//            CodeGenTemplate codeGenTemplateR = cellCodeGenData.getCodeGenTemplate();
//            codeGenTemplateR.setContent(extractFileDesc.getFileContent());
//            addSubTreeNode(tree, mutabLeTreeNode, treePaneLMark, chiLdNode);
//            /**
//             * 添加关联关系
//             */
//            CodeGenSceneTemplate codeGenSceneTemplate = AbEntity.of(CodeGenSceneTemplate.class);
//            codeGenSceneTemplate.setScene(codeGenScene.getName());
//            codeGenSceneTemplate.setTemplate(codeGenTemplate.getName());
//            CodeGenSceneTemplate ua = BaseDAO.connWrap((conn) -> {
//                return CodeGenSceneTemplateDaoImpl.getInstance().insert(conn, codeGenSceneTemplate);
//            });
//            /**
//             * 更新新添加的变量
//             * 更新界面的展示
//             */
//            codeGenScene.contextKeyAppend(extractFileDesc.getContextKvMap());
//            codeGenScenePanel.fillVelocityContext();
//
//            /**
//             * 更新表
//             * 1.填充一些字段是Null的，换成“”，防止出现异常
//             */
//            codeGenScene.updateFillBlank();
//            BaseDAO.update(CodeGenSceneDaoImpl.getInstance(), codeGenScene);
//            if(null == ua){
//                return Pair.of(false, " add sceneTemplate fail ");
//            }
//            return Pair.of(true, null);
//        });
        return null;
    }

    private String orderGen(DefaultMutableTreeNode sub) {
        String order = "100";
        if (sub.getUserObject() instanceof MTTreeCellCodeGenData) {
            MTTreeCellCodeGenData mtTreeCellCodeGenData = (MTTreeCellCodeGenData) sub.getUserObject();
            if (null != mtTreeCellCodeGenData && null != mtTreeCellCodeGenData.getCodeGenTemplate() && null != mtTreeCellCodeGenData.getCodeGenTemplate().getOrderGen()) {
                order = mtTreeCellCodeGenData.getCodeGenTemplate().getOrderGen();
            }
        }
        return order;
    }


    public void fetchSaveSchema(DefaultMutableTreeNode treeNode, TreePanelMark treePanelMark) {
        CodeGenXRenderConnect connect = TabLeftXRenderUtils.model(treePanelMark.fetchProject());
        DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent();
        MTTreeCellCodeGenXRenderNameTable modelParentCell = (MTTreeCellCodeGenXRenderNameTable)parent.getUserObject();
        if(StringUtils.isBlank(modelParentCell.getModel().getExtColumnJson())){
            CodeGenByVelocityNotifier.notifyError("invalid param");
            return;
        }
        JsonNode jsonNode = JacksonUtils.toJsonNodeIgnoreEX(modelParentCell.getModel().getExtColumnJson());
        String sql = "SELECT id,schema_json FROM trade_single_codegen_model_schema_config WHERE name_model = " + jsonNode.get("nameModel") +" AND scene = \"" + model.getNameTableScene() + "\"";
        Map<String, String> re = HikaricpUtils.queryColumnInvoke(connect.getUrl(), connect.getUsername(), connect.getPassword(), sql, "id", "schema_json");
        panel.fillSchemaJson(re.get("schema_json"));
    }

    /**
     *
     * @param treeNode
     * @param treePanelMark
     */
    public void updateSaveSchema(DefaultMutableTreeNode treeNode, TreePanelMark treePanelMark) {
        CodeGenXRenderConnect connect = TabLeftXRenderUtils.model(treePanelMark.fetchProject());
        DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent();
        MTTreeCellCodeGenXRenderNameTable modelParentCell = (MTTreeCellCodeGenXRenderNameTable)parent.getUserObject();
        if(StringUtils.isBlank(modelParentCell.getModel().getExtColumnJson())){
            CodeGenByVelocityNotifier.notifyError("invalid param");
            return;
        }
        JsonNode jsonNode = JacksonUtils.toJsonNodeIgnoreEX(modelParentCell.getModel().getExtColumnJson());
        String minifiedJson = JsonUtils.minifyJsonWrap(panel.fetchSchemaJson());
        String sql = "UPDATE trade_single_codegen_model_schema_config SET schema_json = ? WHERE name_model = ? AND scene = ? ";
        List<Object> updateParam = Lists.newArrayList();
        updateParam.add(minifiedJson);
        updateParam.add(jsonNode.get("nameModel").asText());
        updateParam.add(model.getNameTableScene());
        boolean re = HikaricpUtils.executeUpdate(connect.getUrl(), connect.getUsername(), connect.getPassword(), sql, updateParam);
    }
}


